from PyQt5.QtWidgets import (
    QWidget,
    QVBoxLayout,
    QLineEdit,
    QHBoxLayout,
    QComboBox,
    QListWidget,
    QButtonGroup,
    QRadioButton,
    QCheckBox,
    QListWidgetItem,
    QSizePolicy,
)
from PyQt5.QtCore import Qt, Signal
from PyQt5.QtGui import QPixmap, QDoubleValidator, QIntValidator
import sys
import os
import json
import subprocess
import copy


# 读取json文件
def read_json(jsonPath=""):
    if not os.path.exists(jsonPath):
        return None
    with open(jsonPath, "r", encoding="utf-8") as file:
        data = json.load(file)
    return data


class UI_Common:
    global CELL_HEIGHT
    CELL_HEIGHT = 30

    def createLayout():
        layout = QHBoxLayout()
        layout.setSpacing(5)
        layout.setContentsMargins(10, 0, 10, 0)
        # 设置背景色
        return layout

    def getWidgetHeight():
        global CELL_HEIGHT
        return CELL_HEIGHT

    def getCellBtnWidth():
        return 60


WIDGET_HEIGHT = UI_Common.getWidgetHeight()
BUTTON_WIDTH = UI_Common.getCellBtnWidth()


class ComboCheckBox(QComboBox):
    signa = Signal(list)

    def __init__(self):  # items==[str,str...]
        super(ComboCheckBox, self).__init__()
        self.activated.connect(self.handleComboBoxClosed)
        self.qLineEdit = QLineEdit()
        self.qLineEdit.setReadOnly(True)
        self.row_num = 0

    def addItems(self, items):
        self.items = items
        self.items.insert(0, "全部")
        self.row_num = len(self.items)
        self.Selectedrow_num = 0
        self.qCheckBox = []
        self.qLineEdit = QLineEdit()
        self.qLineEdit.setReadOnly(True)
        self.qListWidget = QListWidget()
        self.addQCheckBox(0)
        self.qCheckBox[0].stateChanged.connect(self.All)
        for i in range(1, self.row_num):
            self.addQCheckBox(i)
            self.qCheckBox[i].stateChanged.connect(self.show0)
        self.setModel(self.qListWidget.model())
        self.setView(self.qListWidget)
        self.setLineEdit(self.qLineEdit)
        # self.qLineEdit.mousePressEvent = self.show_combobox_popup
        self.setMaxVisibleItems(100)  # 避免滑条的出现引起滑条偷吃标签的问题

    def handleComboBoxClosed(self, index, *args, **kwargs):
        # 处理下拉列表关闭后的逻辑
        data = self.Selectlist()
        self.initSelect(data)

    def show_combobox_popup(self, *args, **kwargs):
        self.showPopup()

    # 补充 初始化选择 data:[name1,name2]
    def initSelect(self, data):
        data = data or []
        selectData = []
        if not data:
            self.clear()
        # print("self.row_num=",self.row_num)
        for i in range(1, self.row_num):
            text = self.qCheckBox[i].text()
            # print("text=",text)
            if data.count(text) != 0:
                self.qCheckBox[i].setCheckState(Qt.Checked)
                selectData.append(text)
        self.qLineEdit.setText(";".join(selectData))

    def addQCheckBox(self, i):
        checkbox = QCheckBox()
        self.qCheckBox.append(checkbox)
        qItem = QListWidgetItem(self.qListWidget)
        self.qCheckBox[i].setText(self.items[i])
        self.qListWidget.setItemWidget(qItem, self.qCheckBox[i])

    def Selectlist(self):
        Outputlist = []
        for i in range(1, self.row_num):
            if self.qCheckBox[i].isChecked():
                Outputlist.append(self.qCheckBox[i].text())
        self.Selectedrow_num = len(Outputlist)
        return Outputlist

    def show0(self):
        show0 = ""
        Outputlist = self.Selectlist()
        self.signa.emit(Outputlist)
        self.qLineEdit.setReadOnly(False)
        self.qLineEdit.clear()
        for i in Outputlist:
            show0 += i + ";"
        if self.Selectedrow_num == 0:
            self.qCheckBox[0].setCheckState(Qt.Unchecked)
        elif self.Selectedrow_num == self.row_num - 1:
            self.qCheckBox[0].setCheckState(Qt.Checked)
        else:
            self.qCheckBox[0].setCheckState(Qt.PartiallyChecked)
        self.qLineEdit.setText(show0)
        self.qLineEdit.setReadOnly(True)

    def All(self, zhuangtai):
        if zhuangtai == Qt.Checked:
            for i in range(1, self.row_num):
                self.qCheckBox[i].setChecked(True)
        elif zhuangtai == Qt.PartiallyChecked:
            if self.Selectedrow_num == 0:
                self.qCheckBox[0].setCheckState(Qt.Checked)
        elif zhuangtai == Qt.Unchecked:
            self.clear()

    def clear(self):
        for i in range(self.row_num):
            self.qCheckBox[i].setChecked(False)

    def changeitemlist(self, itemlist):
        self.items = itemlist
        self.items.insert(0, "全部")
        self.row_num = len(self.items)

        self.Selectedrow_num = 0
        self.qCheckBox = []
        self.qLineEdit = QLineEdit()
        self.qLineEdit.setReadOnly(True)
        self.qListWidget = QListWidget()
        self.addQCheckBox(0)
        self.qCheckBox[0].stateChanged.connect(self.All)
        for i in range(1, self.row_num):
            self.addQCheckBox(i)
            self.qCheckBox[i].stateChanged.connect(self.show0)
        self.setModel(self.qListWidget.model())
        self.setView(self.qListWidget)
        self.setLineEdit(self.qLineEdit)


# 单元格-多选下拉框
class CustomCellComboBoxMultiSelectStr(QWidget):
    def __init__(self, options, *args, **kwargs):
        super().__init__()
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.widget = ComboCheckBox()
        layout.addWidget(self.widget)
        self.setLayout(layout)
        self.setFixedHeight(WIDGET_HEIGHT)

        self._init_select_options(options)
        self._set(options)

    def getValue(self):
        return self._get()

    def setValue(self, value: str = None):
        self._set(value)

    def _get(self):
        return self.widget.Selectlist()

    def _set(self, value: str = None):
        return self.widget.initSelect(value)

    def _init_select_options(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.widget.clear()
        self.widget.addItems(items)


class SelectBox2(QComboBox):
    def __init__(self, parent=None, options=[], flag="", index=0, onChanged=None):
        super().__init__()
        self.parent = parent
        self.index = index
        self.flag = flag
        # self._data = data
        # self.setObjectName("value_"+data.get("name"))
        self.onChangedEvent = onChanged
        self._init_show_items(options)
        # self._set(data.get("value"))
        # self.setFixedHeight(WIDGET_HEIGHT)

    def setValue(self, value: str = None):
        self._set(value)

    def getValue(self):
        return self._get()

    def getData(self):
        return self._get()

    def _get(self):
        return self.itemData(self.currentIndex()) or None

    def _set(self, value: str = None):
        if not value:
            self.setCurrentIndex(-1)
        else:
            for index in range(self.count()):
                if self.itemData(index) == value:
                    self.setCurrentIndex(index)
                    break

    def _init_show_items(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()

        for item in items:
            self.addItem(item.get("title", ""), item.get("value"))
        self.setCurrentIndex(-1)
        self.currentIndexChanged.connect(self.onChanged)
        self.placeholderText = "请选择选项"

    def updateItem(self, data):
        currentText = self.currentText()
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.clear()
        for item in items:
            if isinstance(item, str):
                self.addItem(item, item)
            else:
                self.addItem(item.get("title", ""), item.get("value"))
        if self.findText(currentText) > -1:
            self.setCurrentText(currentText)
        else:
            self.setCurrentIndex(-1)

    def onChanged(self):
        if self.onChangedEvent:
            self.onChangedEvent(self.currentText(), self)


class SelectBox(QComboBox):
    def __init__(self, parent=None, options=[], flag="", index=0, onChanged=None):
        super().__init__()
        self.parent = parent
        self.index = index
        self.flag = flag
        # self._data = data
        # self.setObjectName("value_"+data.get("name"))
        self.onChangedEvent = onChanged
        self._init_show_items(options)
        # self._set(data.get("value"))
        # self.setFixedHeight(WIDGET_HEIGHT)

    def setValue(self, value: str = None):
        self._set(value)

    def getValue(self):
        return self._get()

    def getData(self):
        return self._get()

    def _get(self):
        return self.itemData(self.currentIndex()) or None

    def _set(self, value: str = None):
        if not value:
            self.setCurrentIndex(-1)
        else:
            for index in range(self.count()):
                if self.itemData(index) == value:
                    self.setCurrentIndex(index)
                    break

    def _init_show_items(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()

        for item in items:
            self.addItem(item.get("title", ""), item.get("value"))
        self.setCurrentIndex(-1)
        self.currentIndexChanged.connect(self.onChanged)
        self.placeholderText = "请选择选项"

    def updateItem(self, data):
        currentText = self.currentText()
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.clear()
        for item in items:
            if isinstance(item, str):
                self.addItem(item, item)
            else:
                self.addItem(item.get("title", ""), item.get("value"))
        if self.findText(currentText) > -1:
            self.setCurrentText(currentText)
        else:
            self.setCurrentIndex(-1)

    def onChanged(self):
        if self.onChangedEvent:
            self.onChangedEvent(self.currentText(), self.index, self.flag)


class RadioBtnGroup(QWidget):
    def __init__(self, parent=None, options=[], onChanged=None, isCol=False):
        super().__init__(parent)
        self.parent = parent
        self.isCol = isCol
        if isCol:
            self.layout = QVBoxLayout(self)
        #     self.layout.setContentsMargins(0, self.layout.spacing()-3, 0, self.layout.spacing()-3)
        else:
            self.layout = QHBoxLayout(self)
        #     self.layout.setContentsMargins(0, self.layout.spacing()-3, 0, self.layout.spacing()-3)
        self._init_select_options(options)
        self.onChanged = onChanged
        self.setLayout(self.layout)

    def _init_select_options(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.buttonGroup = QButtonGroup()
        self.buttonGroup.buttonToggled.connect(self.onToggled)
        for index, item in enumerate(items):
            radioBtn = QRadioButton(item.get("value"))

            self.buttonGroup.addButton(radioBtn, index)
            self.layout.addWidget(radioBtn)

    def setValue(self, value: str = None):
        self.setButtonCheckedByText(value)

    def getValue(self):
        if self.buttonGroup.checkedButton():
            return self.buttonGroup.checkedButton().text()
        return ""

    def onToggled(self, btn):
        self.onChanged(btn.text())

    def setButtonCheckedByText(self, text):
        for button in self.buttonGroup.buttons():
            if button.text() == text:
                button.setChecked(True)
                break


class MultRadioBtnGroupNew(QWidget):
    def __init__(self, parent=None, options=[], onChanged=None, isCol=False):
        super().__init__(parent)
        self.parent = parent
        self.isCol = isCol
        if isCol:
            self.layout = QVBoxLayout(self)
        #     self.layout.setContentsMargins(0, self.layout.spacing()-3, 0, self.layout.spacing()-3)
        else:
            self.layout = QHBoxLayout(self)
            self.layout.setContentsMargins(0, 0, 0, 0)
        self._init_select_options(options)
        self.opt_value_title = {}
        self.opt_title_value = {}
        for opt in options:
            self.opt_value_title[opt.get("value")] = opt.get("title")
            self.opt_title_value[opt.get("title")] = opt.get("value")

        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.onChanged = onChanged
        self.setLayout(self.layout)

    def _init_select_options(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.buttonGroup = QButtonGroup()
        for index, item in enumerate(items):
            checkBtn = QCheckBox(item.get("title"))
            self.buttonGroup.addButton(checkBtn, index)
            self.layout.addWidget(checkBtn)
        self.buttonGroup.setExclusive(False)  # 设置为非互斥，允许多个复选框被选中
        self.buttonGroup.buttonClicked[int].connect(self.on_checkbox_clicked)

    def setValue(self, values: list = []):
        titles = []
        for value in values:
            title = self.opt_value_title.get(value)
            if title:
                titles.append(title)
        self.setButtonCheckedByText(titles)

    def getValue(self):
        selected = [
            checkbox.text()
            for checkbox in self.buttonGroup.buttons()
            if checkbox.isChecked()
        ]
        values = []
        for title in selected:
            value = self.opt_title_value.get(title)
            if value:
                values.append(value)

        return values

    def on_checkbox_clicked(self, button_id):
        # checkbox = self.buttonGroup.button(button_id)
        # if checkbox.isChecked():
        #     print(f"Checkbox '{checkbox.text()}' is checked")
        # else:
        #     print(f"Checkbox '{checkbox.text()}' is unchecked"
        pass
        # if self.onChanged:
        #     self.onChanged(btn.text())

    def setButtonCheckedByText(self, values):
        for value in values:
            for button in self.buttonGroup.buttons():
                if button.text() == value:
                    button.setChecked(True)
                    break


class MultRadioBtnGroup(QWidget):
    def __init__(self, parent=None, options=[], onChanged=None, isCol=False):
        super().__init__(parent)
        self.parent = parent
        self.isCol = isCol
        if isCol:
            self.layout = QVBoxLayout(self)
        #     self.layout.setContentsMargins(0, self.layout.spacing()-3, 0, self.layout.spacing()-3)
        else:
            self.layout = QHBoxLayout(self)
            self.layout.setContentsMargins(0, 0, 0, 0)
        self._init_select_options(options)
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.onChanged = onChanged
        self.setLayout(self.layout)

    def _init_select_options(self, data):
        items = []
        if isinstance(data, list):
            items = data
        elif isinstance(data, type(lambda x: x)):
            items = data()
        self.buttonGroup = QButtonGroup()
        for index, item in enumerate(items):
            checkBtn = QCheckBox(item.get("value"))
            self.buttonGroup.addButton(checkBtn, index)
            self.layout.addWidget(checkBtn)
        self.buttonGroup.setExclusive(False)  # 设置为非互斥，允许多个复选框被选中
        self.buttonGroup.buttonClicked[int].connect(self.on_checkbox_clicked)

    def setValue(self, values: list = []):
        self.setButtonCheckedByText(values)

    def getValue(self):
        selected = [
            checkbox.text()
            for checkbox in self.buttonGroup.buttons()
            if checkbox.isChecked()
        ]
        return selected

    def on_checkbox_clicked(self, button_id):
        # checkbox = self.buttonGroup.button(button_id)
        # if checkbox.isChecked():
        #     print(f"Checkbox '{checkbox.text()}' is checked")
        # else:
        #     print(f"Checkbox '{checkbox.text()}' is unchecked"
        pass
        # if self.onChanged:
        #     self.onChanged(btn.text())

    def setButtonCheckedByText(self, values):
        for value in values:
            for button in self.buttonGroup.buttons():
                if button.text() == value:
                    button.setChecked(True)
                    break


class LineEditStr(QLineEdit):
    def __init__(self, parent=None, data={}):
        super().__init__()
        # self._data = data
        # self.setClearButtonEnabled(True)
        # self._set(data.get("value"))
        # self.setObjectName("value_"+data.get("name"))
        self.setPlaceholderText("请输入字符串")
        # self.setFixedHeight(WIDGET_HEIGHT)
        self.isRequire = False
        self.label = ""
        if data.get("require"):
            self.isRequire = True
        if data.get("title"):
            self.label = data.get("title")

    def getValue(self):
        return self._get()

    def setValue(self, value: str = None):
        self._set(value)

    def _get(self):
        return self.text() or None

    def _set(self, value: str = None):
        self.setText(value != None and str(value) or "")

    def getRequire(self):
        return self.isRequire

    def getLable(self):
        return self.label


class LineEditFloat(QLineEdit):
    def __init__(self, parent=None, data={}, scope=[], decimals=None):
        super().__init__()
        # self._data = data
        if scope:
            validator = QDoubleValidator(scope[0], scope[1], -1, self)
        else:
            validator = QDoubleValidator()
        if decimals is not None:
            validator.setDecimals(decimals)
        self.setValidator(validator)
        # self.setClearButtonEnabled(True)
        # self._set(data.get("value"))
        # self.setObjectName("value_"+data.get("name"))
        self.setPlaceholderText("请输入浮点数")
        # self.setFixedHeight(WIDGET_HEIGHT)
        self.isRequire = False
        self.label = ""
        if data.get("require"):
            self.isRequire = True
        if data.get("title"):
            self.label = data.get("title")

    def getValue(self):
        return self._get()

    def setValue(self, value: float = None):
        self._set(value)

    def _get(self):
        value = self.text()
        if value != "":
            try:
                return float(value)
            except ValueError:
                print("输入的不是一个数字字符串")
        return None

    def _set(self, value: float = None):
        if value is None:
            value = ""
        self.setText(str(value))

    def getRequire(self):
        return self.isRequire

    def getLable(self):
        return self.label


class LineEditInt(QLineEdit):
    def __init__(self, parent=None, data={}):
        super().__init__()
        # self._data = data
        validator = QIntValidator()
        self.setValidator(validator)
        # self.setClearButtonEnabled(True)
        # self._set(data.get("value"))
        # self.setObjectName("value_"+data.get("name"))
        self.setPlaceholderText("请输入整数")
        # self.setFixedHeight(WIDGET_HEIGHT)
        self.isRequire = False
        self.label = ""
        if data.get("require"):
            self.isRequire = True
        if data.get("title"):
            self.label = data.get("title")

    def getValue(self):
        return self._get()

    def setValue(self, value: int = None):
        self._set(value)

    def _get(self):
        value = self.text()
        if value != "":
            try:
                return int(value)
            except ValueError:
                print("输入的不是一个数字字符串")
        return None

    def _set(self, value: int = None):
        if value is None:
            value = ""
        self.setText(str(value))

    def getRequire(self):
        return self.isRequire

    def getLable(self):
        return self.label
